<!DOCTYPE html>
<html>
<!--
Copyright 2010 The Closure Library Authors. All Rights Reserved.

Use of this source code is governed by the Apache License, Version 2.0.
See the COPYING file for details.
-->
<head>
  <title>goog.Timer, goog.async.Throttle goog.async.Delay</title>
  <script src="../base.js"></script>

  <script>
    goog.require('goog.async.Delay');
    goog.require('goog.async.Throttle');
    goog.require('goog.Timer');
    goog.require('goog.dom');
  </script>

  <link rel="stylesheet" href="css/demo.css">
  <style>
     .userStatus {
       font-style: italic;
       font-weight: bold;
     }
  </style>
</head>
<body>
  <h1>A Collection of Time Based Utilities</h1>
  <h2>goog.async.Delay</h2>
  <p>An action can be invoked after some delay.</p>
  Delay (seconds): <input size="2" type="text" id="delaySeconds" value="2">
  <button onclick="doDelay()">Start Delay</button>
  <button onclick="doReset()">Restart Delay</button>
  <br />
  Delay Status: <span class="userStatus" id="delayStatus">Not Set</span>

  <h2>goog.async.Throttle</h2>
  A throttle prevents the action from being called more than once per time
  interval.
  <br />
  'Create' the Throttle, then hit the 'Do Throttle' button a lot
  of times. Notice the number of 'Hits' increasing with each button press.
  <br />
  The action will be invoked no more than once per time interval.
  <p>
  Throttle interval (seconds):
  <input size="2" type="text" id="throttleSeconds" value="2">
  <button onclick="doThrottleStart()">Create Throttle</button>
  <button onclick="doThrottle()">Do Throttle</button>
  <br />
  Throttle Hits: <span class="userStatus" id="throttleHits"></span>
  <br />
  Throttle Action Called: <span class="userStatus" id="throttleStatus"></span>
  </p>
  <h2>goog.Timer</h2>
  A timer can be set up to call a timeout function on every 'tick' of the timer.
  <p>
  Timer interval (seconds):
  <input size="2" type="text" id="timerSeconds" value="1">
  <button onclick="doTimerStart()">Start Timer</button>
  <button onclick="doTimerStop()">Stop Timer</button>
  <button onclick="doTimerRestart()">Restart Timer</button>
  <br />
  Timer Status: <span class="userStatus" id="timerStatus">Not Set</span>
  </p>
  <h2>goog.Timer.callOnce</h2>
  Timer also has a useful utility function that can call an action after some
  timeout.
  <br />
  This a shortcut/replacement for window.setTimeout, and has a
  corresponding goog.Timer.clear as well, which stops the action.
  <p>
  Timeout (seconds): <input size="2" type="text" id="doOnceSeconds" value="2">
  <button onclick="doOnce()">Go</button>
  <button onclick="doOnceClear()">Clear</button>
  <br />
  Do Once Status: <span class="userStatus" id="doOnceStatus"></span>
  </p>
  <script>

    /**
     * Get the seconds from a document element.
     * @param {string} id The id of the element
     * @return {number}
     */
    var getSeconds = function (id) {
      var time = Number(goog.dom.getElement(id).value);
      if (isNaN(time)) {
        alert('Please enter a Number');
        return null;
      } else {
        return time;
      }
    };

    /**
     * Convert seconds to ms.
     * @param {number} seconds The time in Seconds
     * @return {number}
     */
    var inMs = function (seconds) {
      return seconds * 1000;
    };

    /**
     * Delay.
     */

    var delay = null;
    var delayStatus = goog.dom.getElement('delayStatus');

    /**
     * Start the delay, on the button press.
     */
    var doDelay = function() {
      if (delay) {
        goog.dom.setTextContent(delayStatus, 'Delay already set.');
        return;
      }

      var seconds = getSeconds('delaySeconds');
      if (!goog.isNumber(seconds)) {
        return;
      }
      delay = new goog.async.Delay(delayedAction, inMs(seconds));
      delay.start();
      goog.dom.setTextContent(delayStatus,
                              'Delay for: ' + seconds + ' seconds.');
    };

    /**
     * Reset the delay.
     */
    var doReset = function(){
      if (!delay) {
        return;
      }
      goog.dom.setTextContent(delayStatus, 'Delay Restarted.');
      delay.start();
    };

    /**
     * Callback, after some delay.
     */
    var delayedAction = function() {
      goog.dom.setTextContent(delayStatus, 'Action called.');
      delay.dispose();
      delay = null;
    };

    /**
     * Throttle.
     */

    var throttle = null;
    var throttleCount = 0;
    var throttleFireCount = 0;
    var throttleHits = goog.dom.getElement('throttleHits');
    var throttleStatus = goog.dom.getElement('throttleStatus');

    /**
     * Start a Throttle.
     */
    var doThrottleStart = function() {
      var seconds = getSeconds('throttleSeconds');
      if (!goog.isNumber(seconds)) {
        return;
      }
      // Get rid of an old one, if it exists.
      if (throttle) {
        throttle.dispose();
        throttleCount = 0;
        throttleFireCount = 0;
      }
      // Create the throttle object for the given time.
      throttle = new goog.async.Throttle(throttleAction, inMs(seconds));
      // Reset the hits and the count.
      goog.dom.setTextContent(throttleHits, throttleFireCount);
      goog.dom.setTextContent(throttleStatus, throttleCount);
    };

    /**
     * Do the throttle action, this can be called as often as desired.
     */
    var doThrottle = function(){
      if (throttle) {
        // Fire the throttle, this will only actually 'fire' no more than
        // once per interval.
        throttle.fire();
        goog.dom.setTextContent(throttleHits, ++throttleFireCount);
      }
    };

    /**
     * Throttle Action Callback.
     */
    var throttleAction = function() {
      goog.dom.setTextContent(throttleStatus, ++throttleCount);
    };

    /**
     * Timer.
     */

    var timer = null;
    var timerStatus = goog.dom.getElement('timerStatus');
    var tickCount = 0;

    /**
     * Start a timer.
     */
    var doTimerStart = function() {
      var seconds = getSeconds('timerSeconds');
      if (!goog.isNumber(seconds)) {
        return;
      }
      if (timer) {
        timer.dispose();
        tickCount = 0;
      }
      // A timer can be created with no callback object,
      // listen for the TICK event.
      timer = new goog.Timer(inMs(seconds));
      timer.start();
      goog.events.listen(timer, goog.Timer.TICK, tickAction);
    };

    /**
     * Stop the Timer.
     */
    var doTimerStop = function() {
      if (timer) {
        timer.stop();
       }
    };

    /**
     * Reset the Timer.
     */
    var doTimerRestart = function() {
      if (timer) {
        timer.start();
      }
    };

    /**
     * Tick callback, called whenever the Timer sends a TICK event.
     */
    var tickAction = function() {
      tickCount++;
      goog.dom.setTextContent(timerStatus, 'Got tick: ' + tickCount);
    };

    var doOnceTimer = null;
    var doOnceStatus = goog.dom.getElement('doOnceStatus');

    /*
     * Do some action once, optional delay.  Can not be restarted, like Delay,
     * only cleared.
     */
    var doOnce = function() {
      if (doOnceTimer) {
        // Timer already set, do not reset it.
        return;
      }
      var seconds = getSeconds('doOnceSeconds');
      if (!goog.isNumber(seconds)) {
        return;
      }
      goog.dom.setTextContent(doOnceStatus, 'Will call action in ' + seconds +
          ' seconds.');
      doOnceTimer = goog.Timer.callOnce(function() {
          goog.dom.setTextContent(doOnceStatus, 'Action called.');
          doOnceTimer = null;
          }, inMs(seconds));
    };

    /*
     * Clear the doOnce, do not do the action.
     */
    var doOnceClear = function() {
      goog.Timer.clear(doOnceTimer);
      doOnceTimer = null;
      goog.dom.setTextContent(doOnceStatus,
                              'Timer cleared, action not called.');
    };

  </script>
</body>
</html>
